from typing import List, Set

from fastapi import Depends
from tortoise.expressions import Q

from .user_manager import manager, NotAuthenticatedException
from ..models import User, Dept, Role


class DataScopeFilter:
    """数据权限过滤器 - 基于用户角色的查询条件构建"""
    def __init__(
        self,
        user_field: str = "user_id",
        dept_field: str = "dept_id",
    ):
        self.user_field = user_field
        self.dept_field = dept_field

    async def __call__(self, user: User = Depends(manager)) -> Q:
        if not user:
            raise NotAuthenticatedException("用户未登录")

        await user.fetch_related("dept", "roles")

        roles = user.roles
        if not roles:
            return self._get_self_query(user.id)
        if "admin" in [role.code for role in roles]:
            return Q()

        max_scope = max(role.data_scope for role in roles)

        if max_scope == 4:
            return Q()  # 全部数据
        elif max_scope == 3:
            return await self._get_custom_query(user, roles)
        elif max_scope == 2:
            return await self._get_dept_and_children_query(user)
        elif max_scope == 1:
            return await self._get_dept_query(user)
        else:
            return self._get_self_query(user.id)

    def _get_self_query(self, user_id: int) -> Q:
        """仅本人数据"""
        conditions = Q(**{self.user_field: user_id})
        return conditions

    async def _get_dept_query(self, user) -> Q:
        """本部门数据"""
        if not user.dept:
            return Q(**{self.dept_field: -1})

        # ✅ 直接使用部门ID
        conditions = Q(**{self.dept_field: user.dept.id})
        return conditions

    async def _get_dept_and_children_query(self, user) -> Q:
        """本部门及以下数据"""
        if not user.dept:
            return self._get_self_query(user.id)

        # ✅ 正确做法：先查出所有部门ID，再用 IN 查询
        dept_ids = await self._get_dept_ids_with_children(user.dept.id)

        # 使用 IN 查询
        conditions = Q(**{f"{self.dept_field}__in": dept_ids})

        return conditions

    async def _get_custom_query(self, user: User, roles: List[Role]) -> Q:
        """自定义数据权限"""
        # 筛选出数据权限为自定义(3)的角色
        custom_roles = [role for role in roles if role.data_scope == 3]
        
        if not custom_roles:
            # 没有自定义权限的角色，返回空结果（查询不到数据的条件）
            return Q(id__lte=0)  # 使用一个永远不会匹配到数据的条件，确保不会返回数据
        
        dept_ids: Set[int] = set()
        
        # 批量获取角色关联的部门
        # 注意：这里不使用单独的fetch_related，而是让每个角色单独获取其部门
        # 这是因为Tortoise ORM的fetch_related不支持批量获取多个对象的关联
        for role in custom_roles:
            await role.fetch_related("depts")  # 使用正确的字段名depts
            dept_ids.update(dept.id for dept in role.depts)
        
        # 获取本部门及以下数据的查询条件
        dept_ids_with_children = await self._get_dept_ids_with_children(user.dept.id)
        dept_ids.update(dept_ids_with_children)
        
        if dept_ids:
            # 构建部门ID的查询条件（自定义选择的部门）
            conditions = Q(**{f"{self.dept_field}__in": list(dept_ids)})
        else:
            conditions = Q(**{f"{self.dept_field}__in": []})
        return conditions

    @staticmethod
    async def _get_dept_ids_with_children(dept_id: int) -> List[int]:
        """
        获取部门及其所有子部门的ID列表

        例如：
        - 查询部门2及其子部门
        - 返回: [2, 3, 4] (2本身 + 所有ancestors包含/2/的部门)
        """

        dept_ids = [dept_id]

        # 查询所有子孙部门
        children = await Dept.filter(ancestors__startswith=f"/{dept_id}/").values_list("id", flat=True)

        dept_ids.extend(children)

        return dept_ids


# 使用示例
# get_data_scope = DataScopeFilter()


# @router.get("/users")
# async def get_users(
#     query_filter: Q = Depends(get_data_scope),
# ):
#     """获取用户列表（带数据权限过滤）"""
#     users = await User.filter(query_filter).all()
#     return users
